{
    "cells": [
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "# GcodeControls adjust how a ***design*** is transformed into a 'gcode' ***result***\n",
                "\n",
                "***designs*** are transformed into 'gcode' according to some default settings which can be overwritten with a GcodeControls object with the following attributes (all demonstrated in this notebook):\n",
                "\n",
                "- `save_as` - used to save the gcode directly to a .gcode file\n",
                "- `include_date` - append filename with date+time (default: True)\n",
                "- `printer_name` - used to choose which printer the gcode should be formatted for\n",
                "    - a selection of printers are built in, which is expected to be extended. documentation for adding new printers will be provided in the future\n",
                "- `initialization_data` - used to change the initial print conditions/settings that are established before the steps in the ***design*** are evaluated\n",
                "\n",
                "<*this document is a jupyter notebook - if they're new to you, check out how they work:\n",
                "[link](https://www.google.com/search?q=ipynb+tutorial),\n",
                "[link](https://jupyter.org/try-jupyter/retro/notebooks/?path=notebooks/Intro.ipynb),\n",
                "[link](https://colab.research.google.com/)*>\n",
                "\n",
                "*run all cells in this notebook in order (keep pressing shift+enter)*"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "import fullcontrol as fc"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## save to file\n",
                "\n",
                "use the `save_as` attribute of a GcodeControls object to save the gcode to a file in the same directory as this notebook, with the filename appended by date and time\n",
                "\n",
                "set `include_date` = False to remove date and time"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "steps = []\n",
                "steps.append(fc.Point(x=30, y=30, z=0.2))\n",
                "steps.append(fc.Point(x=60))\n",
                "# option 1 (use built-in function):\n",
                "gcode_controls = fc.GcodeControls(save_as='my_design') # filename includes date+time\n",
                "fc.transform(steps, 'gcode', gcode_controls)\n",
                "gcode_controls = fc.GcodeControls(save_as='my_design', include_date = False) # filename doesn't include date+time\n",
                "fc.transform(steps, 'gcode', gcode_controls)\n",
                "# option 2 (save gcode string to file manually):\n",
                "gcode = fc.transform(steps, 'gcode')\n",
                "open('my_file.gcode', 'w').write(gcode)"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## choose printer\n",
                "\n",
                "change which printer to output gcode for with the 'printer_name' attribute\n",
                "\n",
                "current options:\n",
                "\n",
                "- 'generic' *(default)*\n",
                "- 'ultimaker2plus'\n",
                "- 'prusa_i3'\n",
                "- 'ender_3'\n",
                "- 'cr_10'\n",
                "- 'bambulab_x1'\n",
                "- 'toolchanger_T0'\n",
                "- 'toolchanger_T1'\n",
                "- 'toolchanger_T2'\n",
                "- 'toolchanger_T3'\n",
                "- 'custom'\n",
                "\n",
                "the option 'generic' is default and outputs gcode with no start/end gcode except for the command M83, since omitting this command is a common source of error\n",
                "\n",
                "the option 'custom' doesn't generate any start_gcode at all and allows custom starting procedures to be created as demonstrated later in this notebook"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "steps = []\n",
                "steps.append(fc.Point(x=30, y=30, z=0.2))\n",
                "steps.append(fc.Point(x=60))\n",
                "gcode_controls = fc.GcodeControls(printer_name='toolchanger_T0', save_as='my_design')\n",
                "fc.transform(steps, 'gcode', gcode_controls)"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## change initial settings\n",
                "\n",
                "the 'initialization_data' attribute is used to pass a python 'dictionary' capturing information about printing conditions/settings at the start of the printing process\n",
                "\n",
                "currently, the dictionary can contain any of the aspects listed below\n",
                "\n",
                "a description or the object type ([defined in state objects notebook](state_objects.ipynb)) is displayed next to each term along with default values - individual printers may over-ride these default values or they can be manually over-ridden by including them in the dictionary that is passed to the fc.transform() function when it generates gcode\n",
                "\n",
                "- 'print_speed': 1000 - Printer(print_speed)\n",
                "- 'travel_speed': 8000 - Printer(travel_speed)\n",
                "- 'area_model': 'rectangle' - ExtrusionGeometry(area_model)\n",
                "- 'extrusion_width': 0.4 - ExtrusionGeometry(width)\n",
                "- 'extrusion_height': 0.2 - ExtrusionGeometry(height)\n",
                "- 'nozzle_temp': 210 - Hotend(temp)\n",
                "- 'bed_temp': 40 - Buildplate(temp)\n",
                "- 'fan_percent': 100 - Fan(speed_percent)\n",
                "- 'print_speed_percent': 100 - used in start_gcode for an M220 command\n",
                "- 'material_flow_percent': 100 - used in start_gcode for an M221 command\n",
                "- 'e_units': 'mm' - Extruder(units)\n",
                "- 'relative_e': True - Extruder(relative_gcode)\n",
                "- 'dia_feed': 1.75 - Extruder(dia_feed)\n",
                "- 'primer': 'front_lines_then_y' - see later section about built-in primer options"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### default settings"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "steps = [fc.Point(x=30, y=30, z=0.2), fc.Point(x=60)]\n",
                "print(fc.transform(steps, 'gcode'))"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### initial speed and fan\n",
                "\n",
                "as described above, the default printer is called 'generic' and outputs gcode with no start/end gcode except for the command M83. however, overriding an initial setting results in the appropriate gcode being added to start_gcode"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "steps = [fc.Point(x=30, y=30, z=0.2), fc.Point(x=60)]\n",
                "initial_settings = {\n",
                "    \"print_speed\": 2000,\n",
                "    \"travel_speed\": 4000,\n",
                "    \"nozzle_temp\": 280,\n",
                "    \"bed_temp\": 80,\n",
                "    \"fan_percent\": 40,\n",
                "}\n",
                "gcode_controls = fc.GcodeControls(initialization_data=initial_settings)\n",
                "print(fc.transform(steps, 'gcode', gcode_controls))"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### extrusion width and parameters that affect E in gcode"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "steps = [fc.Point(x=30, y=30, z=0.2), fc.Point(x=60)]\n",
                "initial_settings = {\n",
                "    \"extrusion_width\": 0.8,\n",
                "    \"extrusion_height\": 0.3,\n",
                "    \"e_units\": \"mm3\",\n",
                "    \"relative_e\": False,\n",
                "    \"dia_feed\": 2.85,\n",
                "}\n",
                "gcode_controls = fc.GcodeControls(initialization_data=initial_settings)\n",
                "print(fc.transform(steps, 'gcode', gcode_controls))"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### setting flow % and speed %\n",
                "\n",
                "these aspects change the over-ride values for speed % (gcode M220) and flow % (gcode M221). They don't change the values written for F terms and E terms in gcode. The printer display screen should show these values correctly during printing and allow them to be changed after the print has started"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "steps = [fc.Point(x=30, y=30, z=0.2), fc.Point(x=60)]\n",
                "initial_settings = {\n",
                "    \"print_speed_percent\": 100,\n",
                "    \"material_flow_percent\": 100,\n",
                "}\n",
                "gcode_controls = fc.GcodeControls(initialization_data=initial_settings)\n",
                "print(fc.transform(steps, 'gcode', gcode_controls))"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### primer\n",
                "\n",
                "some basic options to add a primer before your design begins printing are included in this release of FullControl. a good alternative to using a built-in primer, is to manually design a primer at the beginning of the list of steps in a ***design***. such a primer can be truly optimized for the individual design to ensure printing begins perfectly and to minimize the risk of first-layer defects. see an example of this below\n",
                "\n",
                "current options for primers are:\n",
                "\n",
                "- 'front_lines_then_x' - this involves printing some lines on the front of the bed before moving in the **x** direction to the start point of the ***design***\n",
                "- 'front_lines_then_y' - similar to above except move in **y** direction\n",
                "- 'front_lines_then_xy' - similar to above except move in diagonal **xy** direction\n",
                "- 'x' - move from the position at the end of start_gcode to the start point of the ***design*** along the **x** direction (after a y-direction move)\n",
                "- 'y' - similar to above except move in x first, then y to the start point\n",
                "- 'xy' - print directly from the end of the start gcode to the start point\n",
                "- 'travel' - travel from the end of the start gcode to the start point\n"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "steps = [fc.Point(x=30, y=30, z=0.2), fc.Point(x=60)]\n",
                "gcode_controls = fc.GcodeControls(initialization_data={\"primer\": \"front_lines_then_xy\"})\n",
                "print(fc.transform(steps, 'gcode', gcode_controls))"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### custom primer\n",
                "\n",
                "an easy way to add a custom primer, is to include it at the beginning of the ***design***\n",
                "\n",
                "set the gcode initialization data to have the 'travel' primer-type to quickly travel to the start point of the custom primer\n",
                "\n",
                "the ***design*** in the following code cell is transformed to a 'plot' ***result*** rather than 'gcode' for ease of inspection"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "design_steps = [fc.polar_to_point(centre=fc.Point(x=0, y=0, z=i*0.005), radius=10+10*(i%2), angle=i) for i in range(500)]\n",
                "primer_steps = fc.spiralXY(fc.Point(x=0, y=0, z=0.2), 2, 8, 0, 4, 128)\n",
                "steps = primer_steps + design_steps\n",
                "steps.append(fc.PlotAnnotation(point=fc.Point(x=2, y=0, z=0.2), label='primer start'))\n",
                "steps.append(fc.PlotAnnotation(point=fc.Point(x=10, y=0, z=0.1), label='design start'))\n",
                "steps.append(fc.PlotAnnotation(point=fc.Point(x=0, y=0, z=10), label='internal spiral-primer ends near the main-design start point'))\n",
                "fc.transform(steps, 'plot')"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## custom printer template\n",
                "\n",
                "add your own printer by updating the code in the following code cell, which uses the 'custom' printer-type and includes appropriate FullControl objects as the first few steps in the ***design***\n",
                "\n",
                "the following commands generate gcode during initialization of the printer in FullControl, and therefore, it's advisable **not** to use them to avoid their associated gcode appearing before your starting procedure:\n",
                "- relative_e / nozzle_temp / bed_temp / fan_percent / print_speed_percent / material_flow_percent / primer\n",
                "\n",
                "instead, these aspects should be controlled by the custom starting procedure at the start of your ***design***, including turning the extruder on at the appropriate time\n",
                "\n",
                "there is also a [dedicated tutorial](https://colab.research.google.com/gist/fullcontrol-xyz/34bfa6fe7de016bcfc909ae9b526470f/custom_start_end_gcode.ipynb) about copying and pasting existing start/end gcode text for use in FullContol"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "# create the initialize procedure (i.e. start_gcode)\n",
                "initial_settings = {\n",
                "    \"extrusion_width\": 0.8,\n",
                "    \"extrusion_height\": 0.3,\n",
                "    \"e_units\": \"mm3\",\n",
                "    \"dia_feed\": 2.85,\n",
                "    \"primer\": \"no_primer\",\n",
                "    \"print_speed\": 2000,\n",
                "    \"travel_speed\": 4000\n",
                "}\n",
                "gcode_controls = fc.GcodeControls(printer_name='custom', initialization_data=initial_settings)\n",
                "starting_procedure_steps = []\n",
                "starting_procedure_steps.append(fc.ManualGcode(text='\\n; #####\\n; ##### beginning of start procedure\\n; #####'))\n",
                "starting_procedure_steps.append(fc.ManualGcode(text='G28 ; home'))\n",
                "starting_procedure_steps.append(fc.GcodeComment(text='heat bed 10 degrees too hot'))\n",
                "starting_procedure_steps.append(fc.Buildplate(temp=60, wait=True))\n",
                "starting_procedure_steps.append(fc.GcodeComment(text='allow bed to cool to the correct temp and heat up nozzle'))\n",
                "starting_procedure_steps.append(fc.Hotend(temp=220, wait=False))\n",
                "starting_procedure_steps.append(fc.Buildplate(temp=50, wait=True))\n",
                "starting_procedure_steps.append(fc.Hotend(temp=220, wait=True))\n",
                "starting_procedure_steps.append(fc.Fan(speed_percent=100))\n",
                "starting_procedure_steps.append(fc.Extruder(relative_gcode=True))\n",
                "starting_procedure_steps.append(fc.Point(x=10, y=10, z=0.4))\n",
                "starting_procedure_steps.append(fc.ManualGcode(text='; #####\\n; ##### end of start procedure\\n; #####\\n'))\n",
                "\n",
                "# create the design\n",
                "design_steps = []\n",
                "design_steps.append(fc.Point(x=0, y=0, z=0.2))\n",
                "design_steps.append(fc.Extruder(on=True))\n",
                "design_steps.append(fc.Point(x=10, y=0, z=0.2))\n",
                "\n",
                "# combine start procedure and design to create the overall procedure\n",
                "steps = starting_procedure_steps + design_steps\n",
                "print(fc.transform(steps, 'gcode', gcode_controls))"
            ]
        }
    ],
    "metadata": {
        "kernelspec": {
            "display_name": "fc",
            "language": "python",
            "name": "python3"
        },
        "language_info": {
            "codemirror_mode": {
                "name": "ipython",
                "version": 3
            },
            "file_extension": ".py",
            "mimetype": "text/x-python",
            "name": "python",
            "nbconvert_exporter": "python",
            "pygments_lexer": "ipython3",
            "version": "3.11.3"
        },
        "orig_nbformat": 4,
        "vscode": {
            "interpreter": {
                "hash": "2b13a99eb0d91dd901c683fa32c6210ac0c6779bab056ce7c570b3b366dfe237"
            }
        }
    },
    "nbformat": 4,
    "nbformat_minor": 2
}
